package com.phiture.erp.basic.core.service.impl;

import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.annotations.VisibleForTesting;
import com.phiture.erp.basic.core.pojo.dto.ErpMaterialUnitPageReqDTO;
import com.phiture.erp.basic.core.pojo.dto.ErpMaterialUnitSaveReqDTO;
import com.phiture.erp.basic.core.service.ErpMaterialService;
import com.phiture.erp.basic.core.service.ErpMaterialUnitService;
import com.phiture.erp.basic.dal.entity.ErpMaterialUnitDO;
import com.phiture.erp.basic.dal.mapper.ErpMaterialUnitMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static com.phiture.erp.common.constants.ErrorCodeConstants.*;

/**
 * @author YH
 * @date 2025/3/28
 */

@Service
@RequiredArgsConstructor
public class ErpMaterialUnitServiceImpl implements ErpMaterialUnitService {

    private final ErpMaterialUnitMapper materialUnitMapper;
    private final ErpMaterialService materialService;

    @Override
    public Long createMaterialUnit(ErpMaterialUnitSaveReqDTO createReqDTO) {
        // 1. 校验名字唯一
        validateMaterialUnitNameUnique(null, createReqDTO.getName());
        // 2. 插入
        ErpMaterialUnitDO unit = BeanUtils.toBean(createReqDTO, ErpMaterialUnitDO.class);
        materialUnitMapper.insert(unit);
        return unit.getId();
    }

    @Override
    public void updateMaterialUnit(ErpMaterialUnitSaveReqDTO updateReqDTO) {
        // 1.1 校验存在
        validateMaterialUnitExists(updateReqDTO.getId());
        // 1.2 校验名字唯一
        validateMaterialUnitNameUnique(updateReqDTO.getId(), updateReqDTO.getName());
        // 2. 更新
        ErpMaterialUnitDO updateObj = BeanUtils.toBean(updateReqDTO, ErpMaterialUnitDO.class);
        materialUnitMapper.updateById(updateObj);
    }

    @Override
    public void deleteMaterialUnit(Long id) {
        // 1.1 校验存在
        validateMaterialUnitExists(id);
        // 1.2 校验物料是否使用
        if (materialService.getMaterialCountByUnitId(id) > 0) {
            throw exception(MATERIAL_UNIT_EXITS_MATERIAL);
        }
        // 2. 删除
        materialUnitMapper.deleteById(id);
    }

    @Override
    public ErpMaterialUnitDO getMaterialUnit(Long id) {
        return materialUnitMapper.selectById(id);
    }

    @Override
    public PageResult<ErpMaterialUnitDO> getMaterialUnitPage(ErpMaterialUnitPageReqDTO pageReqDTO) {
        return materialUnitMapper.selectPage(pageReqDTO, new LambdaQueryWrapperX<ErpMaterialUnitDO>()
                .likeIfPresent(ErpMaterialUnitDO::getName, pageReqDTO.getName())
                .eqIfPresent(ErpMaterialUnitDO::getStatus, pageReqDTO.getStatus())
                .orderByDesc(ErpMaterialUnitDO::getId));
    }

    @Override
    public List<ErpMaterialUnitDO> getMaterialUnitListByStatus(Integer status) {
        return materialUnitMapper.selectList(ErpMaterialUnitDO::getStatus, status);
    }

    @Override
    public List<ErpMaterialUnitDO> getMaterialUnitList(Collection<Long> ids) {
        return materialUnitMapper.selectBatchIds(ids);
    }

    @Override
    public Map<Long, ErpMaterialUnitDO> getMaterialUnitMap(Collection<Long> ids) {
        return convertMap(getMaterialUnitList(ids), ErpMaterialUnitDO::getId);
    }

    @Override
    public Map<Long, String> getMaterialUnitMap() {
        List<ErpMaterialUnitDO> list = materialUnitMapper.selectList(
                Wrappers.lambdaQuery(ErpMaterialUnitDO.class)
                        .eq(ErpMaterialUnitDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
                        .eq(ErpMaterialUnitDO::getDeleted, Boolean.FALSE)
        );
        return convertMap(list, ErpMaterialUnitDO::getId, ErpMaterialUnitDO::getName);
    }

    @VisibleForTesting
    void validateMaterialUnitNameUnique(Long id, String name) {
        ErpMaterialUnitDO materialUnitDO = materialUnitMapper.selectOne(ErpMaterialUnitDO::getName, name);
        if (materialUnitDO == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的字典类型
        if (id == null || !materialUnitDO.getId().equals(id)) {
            throw exception(MATERIAL_UNIT_NAME_DUPLICATE);
        }
    }

    private void validateMaterialUnitExists(Long id) {
        if (materialUnitMapper.selectById(id) == null) {
            throw exception(MATERIAL_UNIT_NOT_EXISTS);
        }
    }

}
